package com.tianji.promotion.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.UserContext;
import com.tianji.promotion.domain.po.Coupon;
import com.tianji.promotion.domain.po.ExchangeCode;
import com.tianji.promotion.domain.po.UserCoupon;
import com.tianji.promotion.enums.CouponStatus;
import com.tianji.promotion.enums.ExchangeCodeStatus;
import com.tianji.promotion.enums.ObtainType;
import com.tianji.promotion.mapper.CouponMapper;
import com.tianji.promotion.mapper.UserCouponMapper;
import com.tianji.promotion.service.IExchangeCodeService;
import com.tianji.promotion.service.IUserCouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.promotion.utils.CodeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * <p>
 * 用户领取优惠券的记录，是真正使用的优惠券信息 服务实现类
 * </p>
 *
 * @author ltd
 * @since 2024-07-04
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class UserCouponServiceImpl extends ServiceImpl<UserCouponMapper, UserCoupon> implements IUserCouponService {
       private final CouponMapper couponMapper;

       private final IExchangeCodeService codeService;

    @Override

    public void collectTheVoucher(Long id) {
        //1.跟据id查询优惠卷
        Coupon coupon = couponMapper.selectById(id);
        //2.判断优惠卷是否为空，优惠卷的是否是手动领取的
        if (ObjectUtil.isEmpty(coupon)||coupon.getObtainWay()== ObtainType.ISSUE){
            throw new BizIllegalException("优惠卷已经没了");
        }
        //3.判断优惠卷的状态是否是进行中的
        if(coupon.getStatus()!= CouponStatus.ISSUING){
            throw new BizIllegalException("优惠卷状态有误");
        }
        //4.判断时间是否是有效时间
        LocalDateTime now = LocalDateTime.now();
        if (coupon.getIssueBeginTime().isBefore(now)||coupon.getIssueEndTime().isAfter(now)){
            throw new BizIllegalException("已经超过有效时间");
        }
        Long userId = UserContext.getUser();

        synchronized (userId.toString().intern()) {
            IUserCouponService  userCouponService = (IUserCouponService) AopContext.currentProxy();
            userCouponService.extracted1(coupon, userId);
        }
    }
    @Transactional
    @Override
    public void extracted1(Coupon coupon, Long userId) {


            //1.1获取用户领取该优惠卷的数量1
            Integer count = lambdaQuery().eq(UserCoupon::getUserId, userId)
                    .eq(UserCoupon::getCouponId, coupon.getId())
                    .count();
            //1.2判断已经领取的是否大于最大可领取的最大限额，如果大于则已经满了不能领取了
            if (coupon !=null && count>= coupon.getUserLimit()){
                throw new BizIllegalException("已经领取最大次数了");
            }
            //2.已发放数量加一
            couponMapper.updateIssusNum(coupon.getId());
            //3.存入用户卷数据库
            extracted(coupon, userId);

    }


    @Override
    @Transactional
    public void exchangeCoupon(String code) {
        //1.解析兑换码获取id
        long redeemCodes = CodeUtil.parseCode(code);
        //2.判断是否兑换
        //2.1查询redis兑换码兑换状态 SELECT KEY 4 1  直接用bitmap存入返回的值判断是否是兑换的
          Boolean isExist =codeService.getTheStatusOfTheRedemptionCode(redeemCodes,true);
        //2.2是否已经兑换了
          if (isExist){
            throw new BizIllegalException("兑换码已经兑换过了");
        }
        try {
            //3.判断兑换码是否存    在 ltdtijiao
            //查询兑换码
            ExchangeCode exchangeCode = codeService.getById(redeemCodes);
            if (ObjectUtil.isEmpty(exchangeCode)){
                throw new BadRequestException("优惠券不存在");
            }
            //4.判断兑换码是否过期
            if (!exchangeCode.getExpiredTime().isAfter(LocalDateTime.now())){
                throw new BadRequestException("优惠券发放已经结束或尚未开始");
            }
            //5.判断是否超出领取数量
            //5.1查询优惠卷对应的兑换码的限领数量
            Coupon coupon = couponMapper.selectById(exchangeCode.getExchangeTargetId());
            Long userId = UserContext.getUser();
            //判断已经领取的数量是否小于限额，小于则已发行数量加一，生成用户卷
            extracted1(coupon,userId);
            //6.更新兑换码状态
             codeService.lambdaUpdate()
                     .set(ExchangeCode::getUserId,userId)
                     .set(ExchangeCode::getStatus,ExchangeCodeStatus.USED)
                     .eq(ExchangeCode::getId,exchangeCode.getId())
                     .update();
        } catch (Exception e) {
            //如果中途失败则删除兑换码
            codeService.getTheStatusOfTheRedemptionCode(redeemCodes,false);
             throw e;
        }



    }

    private void extracted( Coupon coupon,Long userId) {
        //修改优惠卷里的的已经发行数量
        //1. 获取UserCoupon对象，存入对象
        UserCoupon userCoupon = new UserCoupon();
        userCoupon.setCouponId(coupon.getId());
        userCoupon.setUserId(userId);
        //1.1获取优惠卷开始使用时间，和优惠卷使用结束时间
        LocalDateTime termBeginTime = coupon.getTermBeginTime();
        LocalDateTime termEndTime = coupon.getTermEndTime();
        LocalDateTime now = LocalDateTime.now();
        //1.2判断是否是天数，如果是天数则在当天领取优惠卷的时候计算天数
        if (coupon.getTermBeginTime()==null){
            termBeginTime= now;
            termEndTime = now.plusDays(coupon.getTermDays());

        }
        userCoupon.setTermBeginTime(termBeginTime);
        userCoupon.setTermEndTime(termEndTime);
    }
}
